import axios from 'axios';
import { getAliyunConfig, validateAliyunConfig } from './aliyunConfig';
import type { AliyunConfig } from './aliyunConfig';
// Embedding响应接口
export interface EmbeddingResponse {
  output: {
    embeddings: Array<{
      embedding: number[];
      text_index: number;
    }>;
    usage: {
      total_tokens: number;
    };
  };
  request_id: string;
}

// Embedding请求接口
export interface EmbeddingRequest {
  model: string;
  input: {
    texts: string[];
  };
}

// 阿里云通义千问Embedding服务类
export class AliyunEmbeddingService {
  private config: AliyunConfig;

  constructor(config?: Partial<AliyunConfig>) {
    this.config = { ...getAliyunConfig(), ...config };
    
    if (!validateAliyunConfig(this.config)) {
      throw new Error('阿里云配置不完整，请检查API Key等配置');
    }
  }

  /**
   * 生成文本的embedding向量
   * @param texts 要向量化的文本数组
   * @returns Promise<number[][]> 向量数组
   */
  async generateEmbeddings(texts: string[]): Promise<number[][]> {
    try {
      const requestData: EmbeddingRequest = {
        model: this.config.embeddingModel,
        input: {
          texts: texts
        }
      };

      const response = await axios.post<EmbeddingResponse>(
        `${this.config.baseUrl}/services/embeddings/text-embedding-v1/text-embedding`,
        requestData,
        {
          headers: {
            'Authorization': `Bearer ${this.config.apiKey}`,
            'Content-Type': 'application/json',
            'X-DashScope-SSE': 'disable'
          }
        }
      );

      // 按原始顺序返回embeddings
      const embeddings = new Array(texts.length);
      response.data.output.embeddings.forEach(item => {
        embeddings[item.text_index] = item.embedding;
      });

      return embeddings;
    } catch (error) {
      console.error('生成embedding失败:', error);
      throw new Error(`Embedding生成失败: ${error instanceof Error ? error.message : '未知错误'}`);
    }
  }

  /**
   * 生成单个文本的embedding向量
   * @param text 要向量化的文本
   * @returns Promise<number[]> 向量
   */
  async generateEmbedding(text: string): Promise<number[]> {
    const embeddings = await this.generateEmbeddings([text]);
    return embeddings[0];
  }

  /**
   * 计算两个向量的余弦相似度
   * @param vector1 向量1
   * @param vector2 向量2
   * @returns 余弦相似度 (0-1之间，越接近1越相似)
   */
  static cosineSimilarity(vector1: number[], vector2: number[]): number {
    if (vector1.length !== vector2.length) {
      throw new Error('向量维度不匹配');
    }

    let dotProduct = 0;
    let norm1 = 0;
    let norm2 = 0;

    for (let i = 0; i < vector1.length; i++) {
      dotProduct += vector1[i] * vector2[i];
      norm1 += vector1[i] * vector1[i];
      norm2 += vector2[i] * vector2[i];
    }

    norm1 = Math.sqrt(norm1);
    norm2 = Math.sqrt(norm2);

    if (norm1 === 0 || norm2 === 0) {
      return 0;
    }

    return dotProduct / (norm1 * norm2);
  }

  /**
   * 在知识库中搜索最相似的文本
   * @param query 查询文本
   * @param knowledgeBase 知识库文本数组
   * @param topK 返回前K个最相似的结果
   * @returns Promise<Array<{text: string, similarity: number, index: number}>> 相似度排序的结果
   */
  async searchSimilarTexts(
    query: string, 
    knowledgeBase: string[], 
    topK: number = 5
  ): Promise<Array<{text: string, similarity: number, index: number}>> {
    try {
      // 生成查询文本的embedding
      const queryEmbedding = await this.generateEmbedding(query);
      
      // 生成知识库所有文本的embeddings
      const knowledgeEmbeddings = await this.generateEmbeddings(knowledgeBase);
      
      // 计算相似度并排序
      const similarities = knowledgeEmbeddings.map((embedding, index) => ({
        text: knowledgeBase[index],
        similarity: AliyunEmbeddingService.cosineSimilarity(queryEmbedding, embedding),
        index
      }));
      
      // 按相似度降序排序并返回前K个
      return similarities
        .sort((a, b) => b.similarity - a.similarity)
        .slice(0, topK);
    } catch (error) {
      console.error('搜索相似文本失败:', error);
      throw new Error(`搜索失败: ${error instanceof Error ? error.message : '未知错误'}`);
    }
  }
}

// 创建默认的embedding服务实例
export const embeddingService = new AliyunEmbeddingService(); 